import JSEncrypt from 'jsencrypt'
import CryptoJS from 'crypto-js'

// RSA公钥（由后端提供）
const RSA_PUBLIC_KEY = `-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCRCeXQTNMExuDbyYUgZzO/d8W3r8fpfIXq58VXyzKz3PSM+jvEE9r8+WMXDeX/H8eLexjMDYOZ+QQSG85HTf0YbcNPiUqtnYNFQTYvIOajJ24Eg3Lg5/ti59ZDZULXyzZ59tn4EocPvFVG7Tqz4bDfWdPG/8CeQpaEqdWnEiW5/wIDAQAB
-----END PUBLIC KEY-----`

/**
 * 生成随机AES密钥
 * @param {number} length 密钥长度（32对应AES-256）
 * @returns {string} 随机密钥
 */
function generateAesKey(length = 32) {
	const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'
	let result = ''
	for (let i = 0; i < length; i++) {
		result += chars.charAt(Math.floor(Math.random() * chars.length))
	}
	return result
}

/**
 * 使用RSA加密AES密钥
 * @param {string} aesKey AES密钥
 * @param {string} publicKey RSA公钥
 * @returns {string} 加密后的密钥(Base64编码)
 */
function encryptAesKeyWithRsa(aesKey, publicKey) {
	const encryptor = new JSEncrypt()
	encryptor.setPublicKey(publicKey)
	return encryptor.encrypt(aesKey)
}

/**
 * 使用AES加密数据
 * @param {object|string} data 要加密的数据
 * @param {string} key AES密钥
 * @returns {object} {iv: 初始化向量, content: 加密内容}
 */
function encryptDataWithAes(data, key) {
	if (typeof data === 'object') {
		data = JSON.stringify(data)
	}

	const iv = CryptoJS.lib.WordArray.random(16) // 随机生成IV
	const encrypted = CryptoJS.AES.encrypt(data, CryptoJS.enc.Utf8.parse(key), {
		iv: iv,
		mode: CryptoJS.mode.CBC,
		padding: CryptoJS.pad.Pkcs7
	})

	return {
		iv: iv.toString(CryptoJS.enc.Base64),
		content: encrypted.toString()
	}
}

/**
 * 混合加密主函数
 * @param {object|string} data 要加密的数据
 * @returns {object} 加密结果 {aesKey: RSA加密的AES密钥, encryptedData: AES加密的数据}
 */
export function hybridEncrypt(data) {
	try {
		// 1. 生成随机AES密钥
		const aesKey = generateAesKey(32) // AES-256

		// 2. 使用RSA加密AES密钥
		const encryptedAesKey = encryptAesKeyWithRsa(aesKey, RSA_PUBLIC_KEY)
		if (!encryptedAesKey) throw new Error('RSA加密失败')

		// 3. 使用AES加密实际数据
		const encryptedData = encryptDataWithAes(data, aesKey)

		return {
			key: encryptedAesKey,
			data: encryptedData.content,
			iv: encryptedData.iv
		}
	} catch (error) {
		console.error('混合加密失败:', error)
		throw error
	}
}